import type { MaybeComputedRef, PointerType, Position } from '@vueuse/core'

interface UseDraggableOptions {
  /**
   * Only start the dragging when click on the element directly
   *
   * @default false
   */
  exact?: MaybeComputedRef<boolean>
  /**
   * Prevent events defaults
   *
   * @default false
   */
  preventDefault?: MaybeComputedRef<boolean>
  /**
   * Prevent events propagation
   *
   * @default false
   */
  stopPropagation?: MaybeComputedRef<boolean>
  /**
   * Element to attach `pointermove` and `pointerup` events to.
   *
   * @default window
   */
  draggingElement?: MaybeComputedRef<
    HTMLElement | SVGElement | Window | Document | null | undefined
  >
  /**
   * Handle that triggers the drag event
   *
   * @default target
   */
  handle?: MaybeComputedRef<HTMLElement | SVGElement | null | undefined>
  /**
   * Pointer types that listen to.
   *
   * @default ['mouse', 'touch', 'pen']
   */
  pointerTypes?: PointerType[]
  /**
   * Initial position of the element.
   *
   * @default { x: 0, y: 0 }
   */
  initialValue?: Position
  /**
   * Callback when the dragging starts. Return `false` to prevent dragging.
   */
  onStart?: (position: Position, event: PointerEvent) => void | false
  /**
   * Callback during dragging.
   */
  onMove?: (position: Position, event: PointerEvent) => void
  /**
   * Callback when dragging end.
   */
  onEnd?: (position: Position, event: PointerEvent) => void
}
/*
 * useDraggable是针对position为fixed的拖拽，这里对存在父子关系的absolute进行特殊处理
 */
export function useAbsoluteDraggable(target: MaybeComputedRef<HTMLElement | SVGElement | null | undefined>, containerElementSelector: string, options?: UseDraggableOptions) {
  const result = useDraggable(target, options)
  // useDraggable是针对position为fixed的拖拽，这里对absolute进行特殊处理
  const styleComputed = computed(() => {
    try {
      const containerOffsetLeft
        = (
          document.querySelector(
            containerElementSelector,
          ) as HTMLDivElement | null
        )?.offsetLeft ?? 0
      const containerOffsetTop
        = (
          document.querySelector(
            containerElementSelector,
          ) as HTMLDivElement | null
        )?.offsetTop ?? 0
      // style.value : left:0px;top:0px;
      const left = Number(
        result.style.value?.slice(
          result.style.value?.indexOf(':') + 1,
          result.style.value?.indexOf('px;'),
        ),
      )
      const top = Number(
        result.style.value?.slice(
          result.style.value?.lastIndexOf(':') + 1,
          result.style.value?.lastIndexOf('px;'),
        ),
      )
      if (left == options?.initialValue?.x && top == options?.initialValue?.y)
        return result.style.value

      return `left:${
        left - containerOffsetLeft > 0 ? left - containerOffsetLeft : 0
      }px;top:${top - containerOffsetTop > 0 ? top - containerOffsetTop : 0}px;`
    }
    catch {
      return result.style.value
    }
  })
  return {
    ...result,
    styleComputed,
  }
}
